//
// Created by kode on 2021/3/8.
//

#ifndef LOX_VM_LOX_VM_H_
#define LOX_VM_LOX_VM_H_

#include <memory>
#include <any>
#include <iostream>
#include <stack>
#include <fstream>

#include "chunk.h"
#include "debug.h"

namespace lox {

template<typename T>
using ChunkPtr_t = std::shared_ptr<Chunk < T>>;

enum InterpretResult {
  INTERPRET_OK,
  INTERPRET_COMPILE_ERROR,
  INTERPRET_RUNTIME_ERROR
};

/**
 * The virtual machine which use template type.
 * @tparam VALUE_TYPE Bytecode constant type.
 */
template<typename VALUE_TYPE>
class VM {
 public:
  VM() {}
  // Init by external chunk
  explicit VM(ChunkPtr_t<VALUE_TYPE> chunk_sp) :
      m_chunk_sp(chunk_sp), m_ip{chunk_sp->m_code.begin()}, m_stack{} {}
  InterpretResult Run();
  InterpretResult Interpret(const std::string &source);
  VALUE_TYPE Pop() {
    VALUE_TYPE value = m_stack.top();
    m_stack.pop();
    return value;
  }
  void Repl();
  void RunFile(const char *path);
 private:
  std::shared_ptr<Chunk < VALUE_TYPE>> m_chunk_sp;
  std::vector<uint8_t>::iterator m_ip;
  // Corresponding the Value stack[STACK_MAX]
  std::stack<VALUE_TYPE> m_stack;
};
}

#endif //LOX_VM_LOX_VM_H_
